<?php
// 应用公共文件
function doMoveDir($source, $target) {

    if (!is_dir($target)) {
        if (!mkdir($target)) {
            return false;
        }
    }
    $d = dir($source);
    while (($entry = $d->read()) !== false) {
        if (is_dir($source . $entry)) {
            if ($entry == "." || $entry == "..") {
                continue;
            } else {
                doMoveDir($source . $entry . '/', $target . $entry . '/');
            }
        } else {
            if (!copy($source . $entry, $target . $entry)) {
                return false;
            }
        }
    }
    return true;
}

function wyuLog($file,$str){
    $file = root_path().$file;
    $fp = fopen($file,'a+');
    fwrite($fp, $str."\n");
    fclose($fp);
}

// 应用公共文件

function checkStoreAction($action){
    $actions=[
        'authLogin',
        'login',
        'storeLayout',
        'getContactData',
        'getConsoleData',
        'getDataStatistics'
    ];
    if(!in_array($action,$actions)){
        return false;
    }
    return true;
}

function checkAgentAction($action){
    $actions=[
        'home',
        'login',
        'storeLayout',
        'getContactData',
        'getConsoleData',
        'getDataStatistics'
    ];
    if(!in_array($action,$actions)){
        return false;
    }
    return true;
}



function checkDateFormat($date)
{
    //匹配日期格式
    if (preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $parts)) {
        //检测是否为日期
        if (checkdate($parts[2], $parts[3], $parts[1]))
            return true;
        else
            return false;
    } else
        return false;
}

//将一个数组的主键作为KEY
function array_by_key($data, $key = 'id')
{
    $return = [];
    foreach ($data as $val) {
        $return[$val[$key]] = $val;
    }
    return $return;
}

function get_img($img, $type = '')
{
    $img = str_replace('\\', '/', $img);
    if (empty($type))
        return $img;
    $imgs = explode('.', $img);
    $imgs[count($imgs) - 1] = $type . '.' . $imgs[count($imgs) - 1];
    return join('.', $imgs);
}


/*
 * 经度纬度 转换成距离
 * $lat1 $lng1 是 数据的经度纬度
 * $lat2,$lng2 是获取定位的经度纬度
 */
function rad($d)
{
    return $d * 3.1415926535898 / 180.0;
}

function get_distance_none($lat1, $lng1, $lat2, $lng2)
{
    $EARTH_RADIUS = 6378.137;
    $radLat1 = rad($lat1);
    //echo $radLat1;
    $radLat2 = rad($lat2);
    $a = $radLat1 - $radLat2;
    $b = rad($lng1) - rad($lng2);
    $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
    $s = $s * $EARTH_RADIUS;
    $s = round($s * 10000);
    return $s;
}

function get_distance($lat1, $lng1, $lat2, $lng2)
{
    $s = get_distance_none($lat1, $lng1, $lat2, $lng2);
    $s = $s / 10000;
    if ($s < 1) {
        $s = round($s * 1000);
        $s .= 'm';
    } else {
        $s = round($s, 2);
        $s .= 'km';
    }
    return $s;
}


/**
 * 根据经纬度和半径计算出范围
 * @param string $lat 纬度
 * @param String $lng 经度
 * @param float $radius 半径 m
 * @return array 范围数组
 */
function calc_scope($lat, $lng, $radius)
{
    $degree = (24901 * 1609) / 360.0;
    $dpmLat = 1 / $degree;
    $radiusLat = $dpmLat * $radius;
    $minLat = $lat - $radiusLat;       // 最小纬度
    $maxLat = $lat + $radiusLat;       // 最大纬度
    $mpdLng = $degree * cos($lat * (3.141592653 / 180));
    $dpmLng = 1 / $mpdLng;
    $radiusLng = $dpmLng * $radius;
    $minLng = $lng - $radiusLng;      // 最小经度
    $maxLng = $lng + $radiusLng;      // 最大经度
    $scope = [
        'minLat' => $minLat,
        'maxLat' => $maxLat,
        'minLng' => $minLng,
        'maxLng' => $maxLng
    ];
    return $scope;
}


/**
 * 判断输入的字符串是否是一个合法的电话号码（仅限中国大陆）
 * @param string $string
 * @return boolean
 */
function is_phone($string)
{
    if (preg_match('/^[0,4,8]\d{2,3}-\d{7,8}$/', $string))
        return true;
    return false;
}

/**
 * 验证手机号
 */
function is_mobile($string)
{
    return preg_match('/^1[3456789]\d{9}$/', $string);
}

//获取安全的JSON 或数组
function security_json_or_array($str)
{
    if (is_array($str)) {
        $datas = $str;
    } else {
        $datas = json_decode($str, true);
        if (json_last_error() != JSON_ERROR_NONE) {
            return [];
        }
    }
    if (empty($datas)) return [];
    $return = [];
    foreach ($datas as $key => $val) {
        if (is_array($val)) {
            $return[$key] = security_json_or_array($val);
        } else {
            $return[$key] = security_editor_textarea($val);
        }
    }
    return $return;
}

//获取安全的textarea
function security_editor_textarea($str)
{
    $farr = [
//        "/\s+/", //过滤多余的空白
        "/<(\/?)(script|i?frame|style|html|body|title|link|meta|\?|\%)([^>]*?)>/isU",
        "/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU"
    ];
    $tarr = [
//        " ",
        "＜\\1\\2\\3＞",
        "\\1\\2",
    ];
    $str = preg_replace($farr, $tarr, $str);

    return $str;
}

//获取安全的HTML
function security_editor_html($str)
{
    $str = security_editor_textarea($str);
    $str = str_replace(["\\r\\n", "\\r", "\\n"], "", $str);
    return $str;
}

//加解密函数

function auth_code($string, $operation = 'ENCODE', $key = '', $expiry = 0)
{
    // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
    $ckey_length = 4;
    // 密匙
    $key = md5($key ? $key : config('auth.code'));
    // 密匙a会参与加解密
    $keya = md5(substr($key, 0, 16));
    // 密匙b会用来做数据完整性验证
    $keyb = md5(substr($key, 16, 16));
    // 密匙c用于变化生成的密文
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) :
        substr(md5(microtime()), -$ckey_length)) : '';
    // 参与运算的密匙
    $cryptkey = $keya . md5($keya . $keyc);
    $key_length = strlen($cryptkey);
    // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，
//解密时会通过这个密匙验证数据完整性
    // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) :
        sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
    $string_length = strlen($string);
    $result = '';
    $box = range(0, 255);
    $rndkey = array();
    // 产生密匙簿
    for ($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
    // 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
    for ($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }
    // 核心加解密部分
    for ($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        // 从密匙簿得出密匙进行异或，再转成字符
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }
    if ($operation == 'DECODE') {
        // 验证数据有效性，请看未加密明文的格式
        if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) &&
            substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)
        ) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
        // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
        return $keyc . str_replace('=', '', base64_encode($result));
    }
    //替换url包成url参数唯一性；
}


/*
 * @param $cardNum string 卡号
 * @param $length  int      每几个为一组
 * @param $division
 *
 */
function format_card_num($cardNum, $glue = ' ', $length = 3)
{
    return implode($glue, str_split($cardNum, $length));
}


/**
 * 判断区间
 * @param $stage_data array 范围数组 如 [99,199,299,399]
 * @param $stage_num integer 需要判断的数字
 * @return int 区间前一位 索引值
 */
function sorts($stage_data, $stage_num)
{
    array_push($stage_data, $stage_num);
    $data = array_unique($stage_data);
    sort($data);
    return array_search($stage_num, $data);
}


function is_image($imgurl)
{
    $ext1 = strtolower(substr($imgurl, strrpos($imgurl, '.')));
    $arr = ['.jpg', '.gif', '.png', '.jpeg'];
    return in_array($ext1, $arr);
}


/**
 * 将元 转换成 分
 * @param float $money 价格浮点数 元
 * @return mixed 价格的 分
 */
function money_to_int($money)
{
    return (int)bcmul($money, 100, 0);
}

/**
 * 价格格式化
 * @param int $money 价格 分
 * @param bool $format 是否格式化 默认 否
 * @return float|string  格式后的价格
 */
function wxb_money_format($money, $format = false)
{
    return $format ? number_format($money / 100, 2) : round($money / 100, 2);
}


/*
 * 线段切割法,分割砍价金额
*/
function line_cut($money, $people)
{
    //获取切割处
    $temp = [];
    while (count($temp) < $people - 1) {
        $number = mt_rand(1, $money - 1);
        $temp[$number] = 1;
    }
    //补头补尾
    $temp[0] = 1;
    $temp[$money] = 1;
    $temp = array_keys($temp);
    sort($temp);
    //循环分配
    $red_packet = [];
    for ($i = 0; $i < $people; $i++) {
        $red_packet[] = $temp[$i + 1] - $temp[$i];
    }
    $max_key = array_search(max($red_packet), $red_packet);
    if ($max_key > 0) {
        list ($red_packet[0], $red_packet[$max_key]) = [$red_packet[$max_key], $red_packet[0]];
    }
    return $red_packet;
}


function check_seven_days($date_begin, $date_end)
{
    //默认返回近七天数据、包括今天
    if ($date_begin && $date_end) {
        if ($date_begin > $date_end) {
            return false;
        }
        if (($date_end - $date_begin) / 86400 > 7) {
            return false;
        }
        $date = ['date_begin' => $date_begin, 'date_end' => $date_end];
    } else {
        $date_begin = strtotime(date("Y-m-d", time()));
        $date_end = $date_begin + 86400;
        $date = ['date_begin' => $date_begin, 'date_end' => $date_end];
    }
    return $date;
}

/**
 * 生成订单号
 */
function order_no()
{
    return date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}

/**
 * 判断一个坐标是否在一个多边形内（由多个坐标围成的）
 * 基本思想是利用射线法，计算射线与多边形各边的交点，如果是偶数，则点在多边形外，否则
 * 在多边形内。还会考虑一些特殊情况，如点在多边形顶点上，点在多边形边上等特殊情况。
 * @param $point array 指定点坐标
 * @param $pts array 多边形坐标 顺时针方向
 */
function is_point_in_polygon($point, $pts)
{
    $N = count($pts);
    $boundOrVertex = true; //如果点位于多边形的顶点或边上，也算做点在多边形内，直接返回true
    $intersectCount = 0;
    $precision = 2e-10; //浮点类型计算时候与0比较时候的容差
    $p1 = 0;
    $p2 = 0;
    $p = $point; //测试点
    $p1 = $pts[0];
    for ($i = 1; $i <= $N; ++$i) {
        if ($p['lng'] == $p1['lng'] && $p['lat'] == $p1['lat']) {
            return $boundOrVertex;
        }

        $p2 = $pts[$i % $N];
        if ($p['lat'] < min($p1['lat'], $p2['lat']) || $p['lat'] > max($p1['lat'], $p2['lat'])) {
            $p1 = $p2;
            continue;
        }

        if ($p['lat'] > min($p1['lat'], $p2['lat']) && $p['lat'] < max($p1['lat'], $p2['lat'])) {
            if ($p['lng'] <= max($p1['lng'], $p2['lng'])) {
                if ($p1['lat'] == $p2['lat'] && $p['lng'] >= min($p1['lng'], $p2['lng'])) {
                    return $boundOrVertex;
                }
                if ($p1['lng'] == $p2['lng']) {
                    if ($p1['lng'] == $p['lng']) {
                        return $boundOrVertex;
                    } else {
                        ++$intersectCount;
                    }
                } else {
                    $xinters = ($p['lat'] - $p1['lat']) * ($p2['lng'] - $p1['lng']) / ($p2['lat'] - $p1['lat']) + $p1['lng'];//cross point of lng
                    if (abs($p['lng'] - $xinters) < $precision) {//overlies on a ray
                        return $boundOrVertex;
                    }
                    if ($p['lng'] < $xinters) {
                        ++$intersectCount;
                    }
                }
            }
        } else {
            if ($p['lat'] == $p2['lat'] && $p['lng'] <= $p2['lng']) {
                $p3 = $pts[($i + 1) % $N];
                if ($p['lat'] >= min($p1['lat'], $p3['lat']) && $p['lat'] <= max($p1['lat'], $p3['lat'])) { //p.lat lies between p1.lat & p3.lat
                    ++$intersectCount;
                } else {
                    $intersectCount += 2;
                }
            }
        }
        $p1 = $p2;
    }
    if ($intersectCount % 2 == 0) {//偶数在多边形外
        return false;
    } else { //奇数在多边形内
        return true;
    }
}

/**
 * 检测时间段 是否有交叉
 */
function compare_date($begin, $over)
{
    sort($begin);
    sort($over);
    for ($i = 1; $i < count($begin); $i++) {
        if ($begin[$i] <= $over[$i - 1]) {
            return false;
        }
    }
    return true;
}


/**
 * 根据数组过滤KEY
 * @param array $sampleArray 对比的数组
 * @param array $filterArray 要过滤的数组
 * @return array
 */
function array_filter_key($sampleArray, $filterArray): array
{
    $return = [];
    foreach ($sampleArray as $key => $value) {
        if (is_array($value)) {
            $_data = $filterArray[$key] ?? [];
            $_data = is_array($_data) ? $_data : [];
            //如果是空数组 或者是 索引数组 直接赋值
            if (count($value) == 0 || !\think\helper\Arr::isAssoc($value)) {
                $return[$key] = !\think\helper\Arr::isAssoc($_data) ? $_data : [];
            } else {
                $return[$key] = array_filter_key($value, $_data);
            }

        } else {
            if (!isset($filterArray[$key])) {
                $return[$key] = $value;
            } else {
                $return[$key] = is_array($filterArray[$key]) ? $value : $filterArray[$key];
            }
        }
    }
    return $return;
}

/**
 * 对象转数组
 * @param object $object json 的object
 * @return array
 */
function object_to_array($object): array
{
    return json_decode(json_encode($object), true);
}


/**
 * 数组转对象
 * @param array $data
 * @return object
 */
function array_to_object($data): object
{
    return json_decode(json_encode($data));
}

/**
 * 字符串排序
 * @param $str
 */
function str_sort($str)
{
    $change_after = [];
    for ($i = 0; $i < strlen($str); $i++) {
        if ($str[$i] != ' ') {
            $temp_str = ord($str[$i]);
            $change_after[$i] = $temp_str;
        }
    }
    sort($change_after);
    $rstr = '';
    for ($i = 0; $i < count($change_after); $i++) {
        $rstr .= chr($change_after[$i]);
    }
    return $rstr;
}


function rm_symbol($str)
{
    $char = " 。、！？：；﹑•＂…‘’“”〝〞∕¦‖—　〈〉﹞﹝「」‹›〖〗】【»«』『〕〔》《﹐¸﹕︰﹔！¡？¿﹖﹌﹏﹋＇´ˊˋ―﹫︳︴¯＿￣﹢﹦﹤‐­˜﹟﹩﹠﹪﹡﹨﹍﹉﹎﹊ˇ︵︶︷︸︹︿﹀︺︽︾ˉ﹁﹂﹃﹄︻︼（）";
    $pattern = [
        "/[[:punct:]]/i", //英文标点符号
        '/[' . $char . ']/u', //中文标点符号
        '/[ ]{2,}/',
        '/\s+/',
    ];
    return preg_replace($pattern, '', $str);
}


/**
 * 获取表前缀
 */
function get_table_prefix()
{
    return config("database.connections.mysql.prefix");
}


/**
 * 去除所有空 和换行
 */
function clear_space($str)
{
    $search = [" ", "　", "\n", "\r", "\t"];
    $replace = ["", "", "", "", ""];
    return str_replace($search, $replace, $str);
}


/**
 * @param $v
 * @return mixed
 */
function json_decode_array($v)
{
    $v = htmlspecialchars_decode($v);
    $v = security_editor_html($v);
    return json_decode($v, true);
}

/**
 * 域名是否含有 协议
 * @param string $domain 检测域名
 * @return int
 */
function domain_have_agreement($domain)
{
    $domain = strtolower($domain);
    $preg = "/^http(s)?|ws(s)?|file?|ftp?:\\/\\/.+/";
    return preg_match($preg, $domain);
}

/**
 * 检查是否是合法域名
 */
function check_expire_domain($domain)
{
    $domain = "http://" . $domain;
    return (bool)filter_var($domain, FILTER_SANITIZE_URL, FILTER_FLAG_HOSTNAME);
}

function countage($birthday)
{
    if (date("n") >= date("n", strtotime($birthday))) {
        $month = date("n") - date("n", strtotime($birthday));
        $year = date("Y") - date("Y", strtotime($birthday));
    } else {
        $month = date("n") + 12 - date("n", strtotime($birthday));
        $year = date("Y") - date("Y", strtotime($birthday)) - 1;
    }
    if ($year != 0) {
        if ($month != 0) {
            return $year . "岁" . $month . "个月";
        } else {
            return $year . "岁";
        }
    } else {
        if ($month != 0) {
            return $month . "个月";
        } else {
            return "满月";
        }
    }

}

/**
 * 隐藏手机号中间四位
 * @param $str
 * @return string|string[]
 */
function yc_phone($str){
    if(is_mobile($str)){
        $str=substr_replace($str,'****',3,4);
    }
    return $str;
}

//二维数组排序
function sortArr($arrays,$sort_key,$sort_order=SORT_ASC,$sort_type=SORT_NUMERIC ){
    $key_arrays =array();
    if(is_array($arrays)){
        foreach ($arrays as $array){
            if(is_array($array)){
                $key_arrays[] = $array[$sort_key];
            }else{
                return false;
            }
        }
    }else{
        return false;
    }
    array_multisort($key_arrays,$sort_order,$sort_type,$arrays);
    return $arrays;
}


function array_unique_fb($array2D)
{
    foreach ($array2D as $v)
    {
        $v = join(",",$v);  //降维,也可以用implode,将一维数组转换为用逗号连接的字符串
        $temp[] = $v;
    }

    $temp = array_unique($temp);    //去掉重复的字符串,也就是重复的一维数组
    foreach ($temp as $k => $v)
    {
        $temp[$k] = explode(",",$v);   //再将拆开的数组重新组装
    }
    return $temp;
}

function toHeavy($data,$column){
    $i = [];
    foreach($data as $key => &$value){
        if(in_array($value[$column],$i)){
            unset($data[$key]);
        }else{
            $i = $value;
        }
    }
    return $data;
}



/**
 * 替换图片
 * @param $url 使用的图片链接
 * @param null $pre_url 之前使用的图片链接 null代表第一次上传
 * @return bool
 * @throws \think\db\exception\DataNotFoundException
 * @throws \think\db\exception\DbException
 * @throws \think\db\exception\ModelNotFoundException
 */
function imgReplaceAct($url,$pre_url=null){
    imgNoUseAct($pre_url);
    imgUseAct($url);
   return true;
}

/**
 * 数组里面图片失效
 * @param array $datas
 * @return bool
 * @throws \think\db\exception\DataNotFoundException
 * @throws \think\db\exception\DbException
 * @throws \think\db\exception\ModelNotFoundException
 */
function arrayNoUseImg(array $datas){
    if(!is_array($datas)){
        return false;
    }
    foreach ($datas as $data){
        if(is_array($data)){
            if($data['type']=='pic'){
                imgNoUseAct($data['content']);
            }
        }else{
            imgNoUseAct($data);
        }
    }
    return true;
}

/**
 * 数组里面图片有效
 * @param array $datas
 * @return false
 * @throws \think\db\exception\DataNotFoundException
 * @throws \think\db\exception\DbException
 * @throws \think\db\exception\ModelNotFoundException
 */
function arrayUseImg(array $datas){
    if(!is_array($datas)){
        return false;
    }
    foreach ($datas as $data){
        if(is_array($data)){
            if($data['type']=='pic'){
                imgUseAct($data['content']);
            }
        }else{
            imgUseAct($data);
        }
    }
}



/**
 * 有效的链接
 * @param $url
 * @return bool
 * @throws \think\db\exception\DataNotFoundException
 * @throws \think\db\exception\DbException
 * @throws \think\db\exception\ModelNotFoundException
 */
function imgUseAct($url){
    if(null !== $img = \app\common\model\ImgModel::where([['url','=',$url]])->find()){
        $img->is_use=1;
    }
    $img->save();
    return true;
}

/**
 * 无效的链接
 * @param null $url
 * @return bool
 * @throws \think\db\exception\DataNotFoundException
 * @throws \think\db\exception\DbException
 * @throws \think\db\exception\ModelNotFoundException
 */
function imgNoUseAct($url=null){
    if($url != null){
        if(null !== $img = \app\common\model\ImgModel::where([['url','=',$url]])->find()){
            $img->is_use=0;
        }
        $img->save();
    }
    return true;
}

function distance( $lat1 , $lng1 , $lat2 , $lng2 , $miles = true)
{
  $pi80 = M_PI / 180;
  $lat1 *= $pi80 ;
  $lng1 *= $pi80 ;
  $lat2 *= $pi80 ;
  $lng2 *= $pi80 ;
  $r = 6372.797; // mean radius of Earth in km
  $dlat = $lat2 - $lat1 ;
  $dlng = $lng2 - $lng1 ;
  $a = sin( $dlat /2)*sin( $dlat /2)+ cos ( $lat1 )* cos ( $lat2 )*sin( $dlng /2)*sin( $dlng /2);
  $c = 2 * atan2 (sqrt( $a ), sqrt(1 - $a ));
  $km = $r * $c ;
  return ( $miles ? ( $km * 0.621371192) : $km );
}



